package com.zhongwang.mms.module.material.service;

import com.zhongwang.mms.gen.entity.*;
import com.zhongwang.mms.module.basic.dao.MMaterialDictionaryDao;
import com.zhongwang.mms.module.basic.dao.MMaterialsDao;
import com.zhongwang.mms.module.material.dao.*;
import com.zhongwang.mms.module.material.model.*;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.util.BigDecimalUtils;
import com.zhongwang.mms.util.ShiroUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static com.zhongwang.mms.util.PoiUtils.getValue;
import static com.zhongwang.mms.util.StringUtils.isNumber;

/**
 * @Description: 库存盘点 服务层
 * @Author: China.wsg
 * @Date: 2020/04/29 09:43
 */
@Service
public class MCheckPlanService {

    @Autowired
    private MCheckPlanDao checkPlanDao;
    @Autowired
    private MCheckDetailDao checkDetailDao;
    @Autowired
    private LogService logService;
    @Autowired
    private MAdjustmentApplyDao adjustmentApplyDao;
    @Autowired
    private MInventoryDao inventoryDao;
    @Autowired
    private MMaterialsDao materialsDao;
    @Autowired
    private MMaterialDictionaryDao materialDictionaryDao;
    @Autowired
    private MAdjustDao adjustDao;

    @Value("${user.upload.path}")
    private String uploadPath;

    /**
     * 修改盘点计划
     *
     * @param checkPlan 修改信息
     * @return
     */
    @Transactional
    public int edit(MCheckPlan checkPlan) {

        MCheckPlan oldCheckPlan = checkPlanDao.selectByPrimaryKey(checkPlan.getCpnId());

        logService.saveLog("盘点计划修改", oldCheckPlan, checkPlan);

        checkPlan.setCpnCode(oldCheckPlan.getCpnCode());
        checkPlan.setCpnMaker(oldCheckPlan.getCpnMaker());
        checkPlan.setCpnAccount(oldCheckPlan.getCpnAccount());
        checkPlan.setCpnDate(oldCheckPlan.getCpnDate());
        checkPlan.setCpnStatus(oldCheckPlan.getCpnStatus());
        checkPlan.setCpnResStatus(oldCheckPlan.getCpnResStatus());
        checkPlan.setCpnAdjStatus(oldCheckPlan.getCpnAdjStatus());
        checkPlan.setCpnPalStatus(oldCheckPlan.getCpnPalStatus());
        int row = checkPlanDao.updateByPrimaryKey(checkPlan);
        return row;
    }

    /**
     * 保存盘点计划
     *
     * @param checkPlan 修改信息
     * @return
     */
    @Transactional
    public int save(MCheckPlan checkPlan) {

        // 生产盘点计划编号
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date date = calendar.getTime();

        String cpnCode; // 盘点计划编号：IPC+年月日+3位流水号 MRK200317001
        MCheckPlanExample ex = new MCheckPlanExample();
        ex.setOrderByClause("cpn_id desc");
        MCheckPlanExample.Criteria criteria = ex.createCriteria();
        criteria.andCpnDateGreaterThan(date);
        List<MCheckPlan> checkPlans = checkPlanDao.selectByExample(ex);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if (checkPlans != null && checkPlans.size() > 0) {
            cpnCode = "IPC" + dateFormat.format(new Date()).substring(2) + String.format("%0" + 3 + "d", Integer.parseInt(checkPlans.get(0).getCpnCode().substring(9, 12)) + 1);
        } else {
            cpnCode = "IPC" + dateFormat.format(new Date()).substring(2) + "001";
        }
        checkPlan.setCpnCode(cpnCode);
        checkPlan.setCpnMaker(ShiroUtils.getUser().getName());
        checkPlan.setCpnAccount(ShiroUtils.getLoginName());
        checkPlan.setCpnDate(new Date());
        checkPlan.setCpnStatus(1);
        checkPlan.setCpnResStatus(1);
        checkPlan.setCpnAdjStatus(1);
        checkPlan.setCpnPalStatus(1);

        logService.saveLog("创建盘点计划", "计划编号：" + cpnCode);

        checkPlanDao.insert(checkPlan);
        return checkPlan.getCpnId();
    }

    /**
     * 查询盘点计划列表
     *
     * @param checkPlanModel 查询条件
     * @return 盘点计划列表
     */
    public List<MCheckPlan> findMChangeOrderByQuery(MCheckPlanModel checkPlanModel) {

        return checkPlanDao.findMChangeOrderByQuery(checkPlanModel);
    }

    /**
     * 修改盘点计划状态
     *
     * @param checkPlan 修改信息
     * @return json 数据
     * status含义：0=删除 3=提交 4=撤销
     */
    @Transactional
    public int updateStatus(MCheckPlan checkPlan) {

        String statusName = "";

        // 盘点计划
        MCheckPlan mCheckPlan = checkPlanDao.selectByPrimaryKey(checkPlan.getCpnId());

        if (checkPlan.getCpnStatus() == 0) {
            statusName = "删除";
            mCheckPlan.setCpnStatus(0);
        } else if (checkPlan.getCpnStatus() == 3) {
            statusName = "提交";
            mCheckPlan.setCpnStatus(2);
            mCheckPlan.setCpnResStatus(2);  // 盘点结果 状态
        } else if (checkPlan.getCpnStatus() == 4) {
            mCheckPlan.setCpnStatus(1);
            mCheckPlan.setCpnResStatus(1);
            statusName = "撤销";
        }

        logService.saveLog(statusName + "盘点计划",
                "计划编号：" + mCheckPlan.getCpnCode()
                        + "<br> 盘点内容：" + mCheckPlan.getCpnContent());

        return checkPlanDao.updateByPrimaryKeySelective(mCheckPlan);
    }

    /**
     * 盘点明细查询
     *
     * @param checkDetailModel 查询条件
     * @return
     */
    public List<MCheckDetailModel> findPlanDetailByQuery(MCheckDetailModel checkDetailModel) {

        return checkDetailDao.findPlanDetailByQuery(checkDetailModel);
    }

    /**
     * 获取待盘点明细
     *
     * @param checkDetailModel 查询条件
     * @return
     */
    public List<MCheckDetailModel> findInventoryListByQuery(MCheckDetailModel checkDetailModel) {

        return checkDetailDao.findInventoryListByQuery(checkDetailModel);
    }

    /**
     * 添加库存盘点明细（批量）
     *
     * @param list
     * @return
     */
    @Transactional
    public void addPlanDetail(List<MCheckDetail> list) {

        // 循环存储待标记明细
        for (int i = 0; i < list.size(); i++) {
            checkDetailDao.insert(list.get(i));
        }

        logService.saveLog("添加盘点计划明细", "批量添加数量：" + list.size() + " 条");
    }

    /**
     * 保存盘点结果（单条）
     *
     * @param checkDetail 保存信息
     * @return json 数据
     */
    @Transactional
    public int checkResultSingle(MCheckDetail checkDetail) {

        int rows;
        MCheckDetail oldCheckDetail = checkDetailDao.selectByPrimaryKey(checkDetail.getCdlId());

        // 操作日志保存
        MMaterials materials = materialsDao.selectByPrimaryKey(oldCheckDetail.getCdlMatId());
        MCheckPlan checkPlan = checkPlanDao.selectByPrimaryKey(oldCheckDetail.getCdlCpnId());

        logService.saveLog("录入盘点结果", "计划编号：" + checkPlan.getCpnCode()
                + "<br> 盘点物料：" + materials.getMatNameDesc() + "<br> 盘点数量： " + checkDetail.getCdlNum() + "    盘点重量：" + checkDetail.getCdlWeight());

        // 保存盘点结果
        rows = checkResultSave(checkDetail, oldCheckDetail);

        // 更新盘点结果状态
        updateCpnResStatus(oldCheckDetail.getCdlCpnId());

        return rows;
    }

    /**
     * 更新盘点结果状态
     *
     * @param cpnId
     * @return
     */
    private int updateCpnResStatus(Integer cpnId) {

        // 判断 是否要盘点计划被录入
        MCheckDetailExample ex = new MCheckDetailExample();
        MCheckDetailExample.Criteria criteria = ex.createCriteria();
        criteria.andCdlStatusEqualTo(2);
        criteria.andCdlCpnIdEqualTo(cpnId);
        List<MCheckDetail> checkPlans = checkDetailDao.selectByExample(ex);

        // 创建盘点计划更新对象
        MCheckPlan checkPlan = new MCheckPlan();
        checkPlan.setCpnId(cpnId);
        // 盘点结果状态 1是未开始，2是执行中，3是已完成
        if (checkPlans.size() > 0) {
            checkPlan.setCpnResStatus(2);
        } else {
            checkPlan.setCpnResStatus(1);
        }

        return checkPlanDao.updateByPrimaryKeySelective(checkPlan);
    }

    /**
     * 保存盘点结果
     *
     * @param checkDetail    盘点结果
     * @param oldCheckDetail 现盘点明细
     * @return
     */
    private int checkResultSave(MCheckDetail checkDetail, MCheckDetail oldCheckDetail) {

        int rows;   // 影响数据行数

        // 保存盘点结果
        oldCheckDetail.setCdlNum(checkDetail.getCdlNum());
        oldCheckDetail.setCdlWeight(checkDetail.getCdlWeight());
        if (oldCheckDetail.getCdlNum() == null) {
            oldCheckDetail.setCdlStatus(1); // 状态 1=未盘点 2=已盘点
            oldCheckDetail.setCdlCheckStatus(null);//标识 1=盘盈 2=盘亏
        } else {
            oldCheckDetail.setCdlStatus(2);
            // 盘盈盘亏比较
            int retval = oldCheckDetail.getCdlBeforeWeight().compareTo(oldCheckDetail.getCdlWeight());
            // 盈亏标识 1盘盈 2盘亏
            if (retval < 0) {
                // 1盘盈
                oldCheckDetail.setCdlCheckStatus(1);
            }
            if (retval > 0) {
                // 2盘亏
                oldCheckDetail.setCdlCheckStatus(2);
            }
            if (retval == 0) {
                //
                oldCheckDetail.setCdlCheckStatus(null);
            }
        }
        rows = checkDetailDao.updateByPrimaryKey(oldCheckDetail);

        // 清空对应库存调整明细表
        MAdjustmentApplyExample ex = new MAdjustmentApplyExample();
        MAdjustmentApplyExample.Criteria criteria = ex.createCriteria();
        criteria.andAjaCdlIdEqualTo(oldCheckDetail.getCdlId());
        List<MAdjustmentApply> adjustmentApplies = adjustmentApplyDao.selectByExample(ex);

        // 清空调整表数据
        clearAdjustmentApplie(adjustmentApplies);

        return rows;
    }

    /**
     * 导出盘点明细
     *
     * @param checkDetailModel
     * @param response
     */
    public void exportCheckDetail(MCheckDetailModel checkDetailModel, HttpServletResponse response) {

        List<MCheckDetailModel> model = checkDetailDao.findPlanDetailByQuery(checkDetailModel);

        // 创建HSSFWorkbook对象(excel的文档对象)
        HSSFWorkbook wb = new HSSFWorkbook();
        // 建立新的sheet对象（excel的表单）
        HSSFSheet hssfSheet = wb.createSheet("sheet1");
        // 在sheet里创建第一行，参数为行索引(excel的行)，可以是0～65535之间的任何一个
        HSSFRow hssfRow = hssfSheet.createRow(0);
        // 创建单元格（excel的单元格，参数为列索引，可以是0～255之间的任何一个
        HSSFCell hssfCell = hssfRow.createCell(0);
        // 合并单元格CellRangeAddress构造参数依次表示起始行，截至行，起始列， 截至列
        hssfSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 11));
        // 设置单元格内容
        hssfCell.setCellValue("库存盘点清单" + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        hssfRow = hssfSheet.createRow(1);

        hssfRow.createCell(0).setCellValue("清单ID（禁改）");
        hssfRow.createCell(1).setCellValue("类型（禁改）");
        hssfRow.createCell(2).setCellValue("材质（禁改）");
        hssfRow.createCell(3).setCellValue("规格（禁改）");
        hssfRow.createCell(4).setCellValue("宽度（禁改）");
        hssfRow.createCell(5).setCellValue("长度（禁改）");
        hssfRow.createCell(6).setCellValue("米重/厚度（禁改）");
        hssfRow.createCell(7).setCellValue("在库总数（禁改）");
        hssfRow.createCell(8).setCellValue("在库总量（禁改）");
        hssfRow.createCell(9).setCellValue("库存在库数（禁改）");
        hssfRow.createCell(10).setCellValue("库存在库量（禁改）");
        hssfRow.createCell(11).setCellValue("盘点数量");
        hssfRow.createCell(12).setCellValue("库位（禁改）");

        // 在sheet里创建第二行
        for (int i = 0; i < model.size(); i++) {
            HSSFRow row = hssfSheet.createRow(i + 2);
            row.createCell(0).setCellValue(model.get(i).getCdlId());
            row.createCell(1).setCellValue(model.get(i).getMatTypeName());

            if (!isNumber(model.get(i).getMatQualityName())) {
                row.createCell(2).setCellValue(model.get(i).getMatQualityName());
            } else {
                row.createCell(2).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getMatQualityName())));
            }
            if (!isNumber(model.get(i).getMatSpecName())) {
                row.createCell(3).setCellValue(model.get(i).getMatSpecName());
            } else {
                row.createCell(3).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getMatSpecName())));
            }
            if (model.get(i).getMatWidth() == null) {
                row.createCell(4).setCellValue("");
            } else {
                row.createCell(4).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getMatWidth())));
            }
            if (model.get(i).getMatLength() == null) {
                row.createCell(5).setCellValue("");
            } else {
                row.createCell(5).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getMatLength())));
            }
            if (model.get(i).getMatHeight() == null) {
                row.createCell(6).setCellValue("");
            } else {
                row.createCell(6).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getMatHeight())));
            }
            if (!isNumber(String.valueOf(model.get(i).getCdlBeforeNum()))) {
                row.createCell(7).setCellValue(model.get(i).getCdlBeforeNum());
            } else {
                row.createCell(7).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getCdlBeforeNum())));
            }
            if (!isNumber(String.valueOf(model.get(i).getCdlBeforeWeight()))) {
                row.createCell(8).setCellValue(model.get(i).getCdlBeforeWeight());
            } else {
                row.createCell(8).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getCdlBeforeWeight())));
            }
            if (!isNumber(String.valueOf(model.get(i).getCdlItyNum()))) {
                row.createCell(9).setCellValue(model.get(i).getCdlItyNum());
            } else {
                row.createCell(9).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getCdlItyNum())));
            }
            if (!isNumber(String.valueOf(model.get(i).getCdlItyWeight()))) {
                row.createCell(10).setCellValue(model.get(i).getCdlItyWeight());
            } else {
                row.createCell(10).setCellValue(Double.parseDouble(String.valueOf(model.get(i).getCdlItyWeight())));
            }

            row.createCell(11).setCellValue("");
            row.createCell(12).setCellValue(model.get(i).getMatStockName());
        }

        //输出Excel文件
        try {
            OutputStream output = response.getOutputStream();
            response.reset();
            response.setHeader("Content-disposition", "attachment; filename=inventory.xls");
            response.setContentType("application/msexcel");
            wb.write(output);
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 导入盘点结果
     *
     * @param file  导入文件
     * @param cpnId 盘点计划Id
     * @return
     */
    //Transactional
    public String importFile(MultipartFile file, Integer cpnId) {

        String fileName = file.getOriginalFilename();
        int importCount = 0; // 导入盘点结果

        // 错误数据
        List<ImportCheckDetailModel> errorList = new ArrayList<>();

        Workbook workbook = null;
        try {

            // 判断文件是2007版本还是2010版本
            InputStream is = file.getInputStream();
            if (fileName.endsWith("xlsx")) {
                workbook = new XSSFWorkbook(is);
            }
            if (fileName.endsWith("xls")) {
                workbook = new HSSFWorkbook(is);
            }
            if (workbook != null) {
                //默认读取第一个sheet
                Sheet sheet = workbook.getSheetAt(0);
                ImportCheckDetailModel importInventoryModel;
                // 排除标题行，从第二行开始导入
                for (int i = sheet.getFirstRowNum() + 2; i <= sheet.getLastRowNum(); i++) {

                    Row row = sheet.getRow(i);
                    // 如果行为空忽略
                    if (row == null) {
                        continue;
                    }

                    // 如果盘点数量为空 ，则忽略该行
                    if (StringUtils.isEmpty(getValue(row.getCell(11)))) {
                        continue;
                    }
                    importInventoryModel = new ImportCheckDetailModel();
                    importInventoryModel.setCdlId(getValue(row.getCell(0)));
                    importInventoryModel.setMatTypeName(getValue(row.getCell(1)));
                    importInventoryModel.setMatQualityName(getValue(row.getCell(2)));
                    importInventoryModel.setMatSpecName(getValue(row.getCell(3)));
                    importInventoryModel.setMatWidth(getValue(row.getCell(4)));
                    importInventoryModel.setMatLength(getValue(row.getCell(5)));
                    importInventoryModel.setMatHeight(getValue(row.getCell(6)));
                    importInventoryModel.setCdlBeforeNum(getValue(row.getCell(7)));
                    importInventoryModel.setCdlBeforeWeight(getValue(row.getCell(8)));
                    importInventoryModel.setCdlItyNum(getValue(row.getCell(9)));
                    importInventoryModel.setCdlItyWeight(getValue(row.getCell(10)));
                    CellType cellType = row.getCell(11).getCellType();
                    if (cellType == CellType.NUMERIC) {
                        importInventoryModel.setCdlNum(String.valueOf(row.getCell(11).getNumericCellValue()));
                    } else {
                        importInventoryModel.setCdlNum(getValue(row.getCell(11)));
                    }
                    importInventoryModel.setMatStockName(getValue(row.getCell(12)));

                    // 判断 清单ID（禁改）字段不允许为空
                    if (!StringUtils.isNumeric(String.valueOf(importInventoryModel.getCdlId())) || importInventoryModel.getCdlId() == null) {
                        importInventoryModel.setErrorReason("清单ID（禁改）字段被修改");
                        errorList.add(importInventoryModel);
                    }

                    // 根据清单ID 取得 盘点计划明细信息
                    MCheckDetail checkDetail = checkDetailDao.selectByPrimaryKey(Integer.valueOf(importInventoryModel.getCdlId()));

                    // 判断 盘点计划和导入盘点结果 禁改内容是否一致
                    if (checkDetail == null) {
                        importInventoryModel.setErrorReason("禁改字段被修改");
                        errorList.add(importInventoryModel);
                        continue;
                    }

                    //判断 数量kg 字段是否为数字格式
                    if (!isNumber(importInventoryModel.getCdlNum())) {
                        importInventoryModel.setErrorReason("[数量]字段应该为数字格式，不应含有英文或汉字");
                        errorList.add(importInventoryModel);
                        continue;
                    }

                    // 根据数量计算重量
                    MMaterials materials = materialsDao.selectByPrimaryKey(checkDetail.getCdlMatId());
                    importInventoryModel.setCdlWeight(computeInventoryWeight(materials, importInventoryModel, Double.valueOf(importInventoryModel.getCdlNum())));

                    // 保存盘点明细行
                    checkDetail.setCdlNum(Double.valueOf(importInventoryModel.getCdlNum()));
                    if (importInventoryModel.getCdlWeight() != null) {
                        checkDetail.setCdlWeight(Double.valueOf(importInventoryModel.getCdlWeight()));
                    }
                    checkDetail.setCdlStatus(2);

                    // 盘盈盘亏比较
                    int retval = checkDetail.getCdlBeforeWeight().compareTo(checkDetail.getCdlWeight());

                    // 盈亏标识 1盘盈 2盘亏
                    if (retval < 0) {
                        // 1盘盈
                        checkDetail.setCdlCheckStatus(1);
                    }
                    if (retval > 0) {
                        // 2盘亏
                        checkDetail.setCdlCheckStatus(2);
                    }
                    if (retval == 0) {
                        //
                        checkDetail.setCdlCheckStatus(null);
                    }

                    checkDetailDao.updateByPrimaryKey(checkDetail);
                    importCount++;
                }

                // 保存导入失败数据
                // 创建HSSFWorkbook对象(excel的文档对象)
                HSSFWorkbook wb = new HSSFWorkbook();
                // 建立新的sheet对象（excel的表单）
                HSSFSheet hssfSheet = wb.createSheet("sheet1");
                // 在sheet里创建第一行，参数为行索引(excel的行)，可以是0～65535之间的任何一个
                HSSFRow hssfRow = hssfSheet.createRow(0);
                // 创建单元格（excel的单元格，参数为列索引，可以是0～255之间的任何一个
                HSSFCell hssfCell = hssfRow.createCell(0);
                // 设置单元格内容
                hssfCell.setCellValue("导入失败数据" + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                // 合并单元格CellRangeAddress构造参数依次表示起始行，截至行，起始列， 截至列
                hssfSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 11));
                // 在sheet里创建第二行
                for (int i = 0; i < errorList.size(); i++) {
                    HSSFRow row = hssfSheet.createRow(i + 1);
                    row.createCell(0).setCellValue(errorList.get(i).getCdlId());
                    row.createCell(1).setCellValue(errorList.get(i).getMatTypeName());
                    row.createCell(2).setCellValue(errorList.get(i).getMatQualityName());
                    row.createCell(3).setCellValue(errorList.get(i).getMatSpecName());
                    row.createCell(4).setCellValue(errorList.get(i).getMatWidth());
                    row.createCell(5).setCellValue(errorList.get(i).getMatLength());
                    row.createCell(6).setCellValue(errorList.get(i).getMatHeight());
                    row.createCell(7).setCellValue(errorList.get(i).getCdlBeforeNum());
                    row.createCell(8).setCellValue(errorList.get(i).getCdlBeforeWeight());
                    row.createCell(9).setCellValue(errorList.get(i).getCdlItyNum());
                    row.createCell(10).setCellValue(errorList.get(i).getCdlItyWeight());
                    row.createCell(11).setCellValue(errorList.get(i).getCdlNum());
                    row.createCell(12).setCellValue(errorList.get(i).getMatStockName());
                    row.createCell(13).setCellValue(errorList.get(i).getErrorReason());
                }

                // 保存文件到固定路径
                MCheckPlan checkPlan = checkPlanDao.selectByPrimaryKey(cpnId);
                String path = uploadPath + checkPlan.getCpnCode() + "/";
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File saveFile = new File(path + "inventoryFailed.xls");
                FileOutputStream output = new FileOutputStream(saveFile);
                wb.write(output);//写入磁盘
                output.close();

                // 更新盘点结果状态
                updateCpnResStatus(cpnId);
                logService.saveLog("库存盘点导入", "导入成功：" + importCount + "条， " + "导入失败：" + errorList.size() + "条");
                return errorList.size() > 0 ? "导入失败" : "导入完成";
            } else {
                return "导入失败";
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (Exception ignored) {
                }
            }
        }
        return "导入失败";

    }

    /**
     * 根据盘点数量 返回 盘点数量
     *
     * @param materials
     * @param inventoryQty
     * @return
     */
    private Double computeInventoryWeight(MMaterials materials, ImportCheckDetailModel importCheckDetailModel, Double inventoryQty) {
        Double inventoryWeight = 0.0;

        MMaterialDictionary materialDictionary = materialDictionaryDao.selectByPrimaryKey(materials.getMatSpecId());
        Double spec = isNumber(materialDictionary.getMdName()) ? Double.valueOf(materialDictionary.getMdName()) : 0.0;       // 规格
        Double width = materials.getMatWidth() == null ? 0.0 : materials.getMatWidth();      // 宽度
        Double length = materials.getMatLength() == null ? 0.0 : materials.getMatLength();      // 长度
        Double height = materials.getMatHeight() == null ? 0.0 : materials.getMatHeight();      // 厚度
        Integer formulaType = materials.getMatFormulaType();

        if (formulaType == null) {
            inventoryWeight = null;
        } else if (formulaType == 1) {
            // 重量 =（规格*宽度*长度*数量*7.85/1000）-（(规格-2*米重/厚度)*（宽度-2*米重/厚度）*7.85/1000*数量*长度）
            inventoryWeight = formatRound((spec * width * length * inventoryQty * 7.85 / 1000) - ((spec - 2 * height) * (width - 2 * height) * 7.85 / 1000 * inventoryQty * length));
        } else if (formulaType == 2) {
            // 重量 = 规格*规格*长度*数量*0.00617
            inventoryWeight = formatRound(spec * spec * length * inventoryQty * 0.00617);
        } else if (formulaType == 3) {
            // 重量 = 长度*数量*米重/厚度
            inventoryWeight = formatRound(length * inventoryQty * height);
        } else if (formulaType == 4) {
            // 重量 =（规格-宽度）*宽度*0.02466*长度*数量
            inventoryWeight = formatRound((spec - width) * width * 0.02466 * length * inventoryQty);
        } else if (formulaType == 5) {
            // 重量 = 规格*宽度*长度*2.7/1000000*数量
            inventoryWeight = formatRound(spec * width * length * 2.7 / 1000000 * inventoryQty);
        } else if (formulaType == 6) {
            // 重量 = 规格*宽度*长度*7.85/1000000*数量
            inventoryWeight = formatRound(spec * width * length * 7.85 / 1000000 * inventoryQty);
        }

        if (formulaType != null) {
            double a = BigDecimalUtils.sub(Double.valueOf(importCheckDetailModel.getCdlBeforeNum()), Double.valueOf(importCheckDetailModel.getCdlNum()));
            double b = BigDecimalUtils.sub(Double.valueOf(importCheckDetailModel.getCdlBeforeWeight()), inventoryWeight);
            if (a == 0 && Math.abs(b) < 2) {
                inventoryWeight = Double.valueOf(importCheckDetailModel.getCdlBeforeWeight());
            }
        }

        return inventoryWeight;
    }

    /**
     * 保留两位小数，四舍五入的一个老土的方法
     *
     * @param d
     * @return
     */
    public static double formatRound(double d) {
        return (double) Math.round(d * 100) / 100;
    }

    /**
     * 判断文件是否存在
     *
     * @param url 文件URL
     * @return 是否存在
     */
    public boolean exist(String url) {
        int i = url.lastIndexOf("files/");
        String path = uploadPath + url.substring(i + 6);
        File file = new File(path);
        if (!file.exists()) {
            return false;
        }
        return true;
    }

    /**
     * 盘亏量大于库存在库量数据
     *
     * @param cpnId
     * @param response
     */
    public void exportLossListByPlanId(Integer cpnId, HttpServletResponse response) {

        // 查询盘亏量大于库存在库量数据
        MCheckDetailModel checkDetailModel = new MCheckDetailModel();
        checkDetailModel.setCpnId(cpnId);
        checkDetailModel.setLossFlgQuery(2);
        List<MCheckDetailModel> model = checkDetailDao.findPlanDetailByQuery(checkDetailModel);

        // 创建HSSFWorkbook对象(excel的文档对象)
        HSSFWorkbook wb = new HSSFWorkbook();
        // 建立新的sheet对象（excel的表单）
        HSSFSheet hssfSheet = wb.createSheet("sheet1");
        // 在sheet里创建第一行，参数为行索引(excel的行)，可以是0～65535之间的任何一个
        HSSFRow hssfRow = hssfSheet.createRow(0);
        // 创建单元格（excel的单元格，参数为列索引，可以是0～255之间的任何一个
        HSSFCell hssfCell = hssfRow.createCell(0);
        // 合并单元格CellRangeAddress构造参数依次表示起始行，截至行，起始列， 截至列
        hssfSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 9));
        // 设置单元格内容
        hssfCell.setCellValue("导出盘亏量大于库存在库量数据" + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        hssfRow = hssfSheet.createRow(1);

        hssfRow.createCell(0).setCellValue("清单ID（禁改）");
        hssfRow.createCell(1).setCellValue("类型（禁改）");
        hssfRow.createCell(2).setCellValue("材质（禁改）");
        hssfRow.createCell(3).setCellValue("规格（禁改）");
        hssfRow.createCell(4).setCellValue("宽度（禁改）");
        hssfRow.createCell(5).setCellValue("长度（禁改）");
        hssfRow.createCell(6).setCellValue("米重/厚度（禁改）");
        hssfRow.createCell(7).setCellValue("在库总数（禁改）");
        hssfRow.createCell(8).setCellValue("在库总量（禁改）");
        hssfRow.createCell(9).setCellValue("库存在库数（禁改）");
        hssfRow.createCell(10).setCellValue("库存在库量（禁改）");
        hssfRow.createCell(11).setCellValue("盘点数量");
        hssfRow.createCell(12).setCellValue("盘点重量");
        hssfRow.createCell(13).setCellValue("盘亏重量");
        hssfRow.createCell(14).setCellValue("库位（禁改）");

        // 在sheet里创建第二行
        for (int i = 0; i < model.size(); i++) {
            HSSFRow row = hssfSheet.createRow(i + 2);
            row.createCell(0).setCellValue(model.get(i).getCdlId());
            row.createCell(1).setCellValue(model.get(i).getMatTypeName());
            row.createCell(2).setCellValue(model.get(i).getMatQualityName());
            row.createCell(3).setCellValue(model.get(i).getMatSpecName());
            if (model.get(i).getMatWidth() == null) {
                row.createCell(4).setCellValue("");
            } else {
                row.createCell(4).setCellValue(model.get(i).getMatWidth());
            }
            if (model.get(i).getMatLength() == null) {
                row.createCell(5).setCellValue("");
            } else {
                row.createCell(5).setCellValue(model.get(i).getMatLength());
            }
            if (model.get(i).getMatHeight() == null) {
                row.createCell(6).setCellValue("");
            } else {
                row.createCell(6).setCellValue(model.get(i).getMatHeight());
            }
            row.createCell(7).setCellValue(String.valueOf(model.get(i).getCdlBeforeNum()));
            row.createCell(8).setCellValue(String.valueOf(model.get(i).getCdlBeforeWeight()));
            row.createCell(9).setCellValue(String.valueOf(model.get(i).getCdlItyNum()));
            row.createCell(10).setCellValue(String.valueOf(model.get(i).getCdlItyWeight()));
            row.createCell(11).setCellValue(String.valueOf(model.get(i).getCdlNum()));
            row.createCell(12).setCellValue(String.valueOf(model.get(i).getCdlWeight()));
            row.createCell(13).setCellValue(String.valueOf(model.get(i).getDifferenceValue()));
            row.createCell(14).setCellValue(model.get(i).getMatStockName());
        }

        //输出Excel文件
        try {
            OutputStream output = response.getOutputStream();
            response.reset();
            response.setHeader("Content-disposition", "attachment; filename=details.xls");
            response.setContentType("application/msexcel");
            wb.write(output);
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清空盘点结果
     *
     * @param cpnId 盘点计划Id
     * @return
     */
    @Transactional
    public String clear(Integer cpnId) {

        // 判断 盘点结果状态为 3=已完成 时 不允许清空盘点结果（1是未开始，2是执行中，3是已完成）
        MCheckPlan checkPlan;
        checkPlan = checkPlanDao.selectByPrimaryKey(cpnId);
        if (checkPlan.getCpnResStatus() == 3) {
            return "盘点已完成，不允许清空盘点结果！";
        }

        // 更新盘点结果状态
        checkPlan.setCpnResStatus(1); // 盘点结果状态 1是未开始，2是执行中，3是已完成
        checkPlanDao.updateByPrimaryKeySelective(checkPlan);

        // 清空盘点计划明细已盘点内容
        MCheckDetailExample ex = new MCheckDetailExample();
        MCheckDetailExample.Criteria criteria = ex.createCriteria();
        criteria.andCdlCpnIdEqualTo(cpnId);
        List<MCheckDetail> checkPlans = checkDetailDao.selectByExample(ex);

        if (checkPlans != null && checkPlans.size() > 0) {

            for (int i = 0; i < checkPlans.size(); i++) {

                checkPlans.get(i).setCdlStatus(1);
                checkPlans.get(i).setCdlNum(null);
                checkPlans.get(i).setCdlWeight(null);
                checkPlans.get(i).setCdlCheckStatus(null);

                checkDetailDao.updateByPrimaryKey(checkPlans.get(i));
            }
        }

        // 清空库存调整明细内容
        MAdjustmentApplyExample ex1 = new MAdjustmentApplyExample();
        MAdjustmentApplyExample.Criteria criteria1 = ex1.createCriteria();
        criteria1.andAjaCpnIdEqualTo(cpnId);
        List<MAdjustmentApply> adjustmentApplies = adjustmentApplyDao.selectByExample(ex1);

        // 清空调整表数据
        clearAdjustmentApplie(adjustmentApplies);

        logService.saveLog("清空盘点结果", "盘点计划编号：" + checkPlan.getCpnCode());
        return "清空成功！";
    }

    /**
     * 清空调整表数据
     *
     * @param adjustmentApplies 待清空列表
     */
    private void clearAdjustmentApplie(List<MAdjustmentApply> adjustmentApplies) {
        if (adjustmentApplies != null && adjustmentApplies.size() > 0) {
            for (int i = 0; i < adjustmentApplies.size(); i++) {

                MInventory inventory = inventoryDao.selectByPrimaryKey(adjustmentApplies.get(i).getAjaItyId());
                if (inventory != null && adjustmentApplies.get(i).getAjaWeight() != null) {
                    inventory.setItyAvaNum(BigDecimalUtils.add(inventory.getItyAvaNum(), adjustmentApplies.get(i).getAjaNum()));
                    inventory.setItyAvaWeight(BigDecimalUtils.add(inventory.getItyAvaWeight(), adjustmentApplies.get(i).getAjaWeight()));
                    inventoryDao.updateByPrimaryKeySelective(inventory);
                }
                adjustmentApplyDao.deleteByPrimaryKey(adjustmentApplies.get(i).getAjaId());
            }
        }


    }

    /**
     * 更新盘点状态
     *
     * @param cpnId 盘点计划Id
     * @return
     */
    @Transactional
    public String updateResStatus(Integer cpnId) {

        // 判断 盘点结果状态为 3=已完成 时 不允许清空盘点结果（1是未开始，2是执行中，3是已完成）
        MCheckPlan checkPlan;
        checkPlan = checkPlanDao.selectByPrimaryKey(cpnId);
        if (checkPlan.getCpnAdjStatus() == 3) {
            return "撤销失败，请先撤销盘点损益调整。";
        }

        // 判断 有未盘点 不允许提交
        if (checkPlan.getCpnResStatus() != 3) {
            MCheckDetailExample ex1 = new MCheckDetailExample();
            MCheckDetailExample.Criteria criteria1 = ex1.createCriteria();
            criteria1.andCdlCpnIdEqualTo(cpnId);
            criteria1.andCdlStatusEqualTo(1);   // 1=未盘点 2=已盘点
            List<MCheckDetail> checkDetails = checkDetailDao.selectByExample(ex1);
            if (checkDetails != null && checkDetails.size() > 0) {
                return "提交失败，请将所有盘点计划进行盘点。";
            }
        }

        // 更新盘点状态
        if (checkPlan.getCpnResStatus() == 3) {
            checkPlan.setCpnResStatus(2);
            checkPlan.setCpnAdjStatus(1);
        } else {
            checkPlan.setCpnResStatus(3);
            checkPlan.setCpnAdjStatus(2);
        }
        checkPlanDao.updateByPrimaryKey(checkPlan);

        // 清空调整结果
        MAdjustmentApplyExample ex = new MAdjustmentApplyExample();
        MAdjustmentApplyExample.Criteria criteria1 = ex.createCriteria();
        criteria1.andAjaCpnIdEqualTo(cpnId);
        List<MAdjustmentApply> adjustmentApplies = adjustmentApplyDao.selectByExample(ex);

        // 清空调整表数据
        clearAdjustmentApplie(adjustmentApplies);

        logService.saveLog(checkPlan.getCpnResStatus() == 3 ? "提交盘点结果" : "撤销盘点结果", "盘点计划编号：" + checkPlan.getCpnCode());
        return checkPlan.getCpnResStatus() == 3 ? "提交成功" : "撤销成功";
    }

    /**
     * 新增盘点结果
     *
     * @param checkDetail 保存信息
     * @return json 数据
     */
    @Transactional
    public String saveNewCheckDetail(MCheckDetail checkDetail) {

        // 判断 新增盘点物料是在盘点计划中存在，存在则不允许添加
        MCheckDetailExample ex = new MCheckDetailExample();
        MCheckDetailExample.Criteria criteria1 = ex.createCriteria();
        criteria1.andCdlCpnIdEqualTo(checkDetail.getCdlCpnId());
        criteria1.andCdlMatIdEqualTo(checkDetail.getCdlMatId());
        List<MCheckDetail> checkDetails = checkDetailDao.selectByExample(ex);

        if (checkDetails != null && checkDetails.size() > 0) {
            return "盘点计划中已存在该物料，不允许二次添加！";
        }

        // 添加新增记录
        // 属性字段添加
        MCheckDetailModel checkDetailModel = new MCheckDetailModel();
        checkDetailModel.setCpnId(checkDetail.getCdlCpnId());
        checkDetailModel.setCdlMatId(checkDetail.getCdlMatId());
        List<MCheckDetailModel> checkDetailModels = checkDetailDao.findInventoryListByQuery(checkDetailModel);
        if (checkDetailModels != null && checkDetailModels.size() > 0) {
            checkDetail.setCdlItyNum(checkDetailModels.get(0).getCdlItyNum());
            checkDetail.setCdlItyWeight(checkDetailModels.get(0).getCdlItyWeight());
            checkDetail.setCdlBeforeNum(checkDetailModels.get(0).getCdlBeforeNum());
            checkDetail.setCdlBeforeWeight(checkDetailModels.get(0).getCdlBeforeWeight());
        } else {
            checkDetail.setCdlItyNum(0.0);
            checkDetail.setCdlItyWeight(0.0);
            checkDetail.setCdlBeforeNum(0.0);
            checkDetail.setCdlBeforeWeight(0.0);
        }

        // 属性字段添加
        if (checkDetail.getCdlNum() == null) {
            checkDetail.setCdlStatus(1); // 状态 1=未盘点 2=已盘点
            checkDetail.setCdlCheckStatus(null);//标识 1=盘盈 2=盘亏
        } else {
            checkDetail.setCdlStatus(2);
            // 盘盈盘亏比较
            int retval = checkDetail.getCdlBeforeWeight().compareTo(checkDetail.getCdlWeight());
            // 盈亏标识 1盘盈 2盘亏
            if (retval < 0) {
                // 1盘盈
                checkDetail.setCdlCheckStatus(1);
            }
            if (retval > 0) {
                // 2盘亏
                checkDetail.setCdlCheckStatus(2);
            }
            if (retval == 0) {
                //
                checkDetail.setCdlCheckStatus(null);
            }
        }
        checkDetail.setCdlIsNewFlag(1); // 新增标识 1=新增
        checkDetailDao.insert(checkDetail);

        MCheckPlan checkPlan = checkPlanDao.selectByPrimaryKey(checkDetail.getCdlCpnId());
        MMaterials materials = materialsDao.selectByPrimaryKey(checkDetail.getCdlMatId());
        logService.saveLog("新增盘点记录", "计划编码：" + checkPlan.getCpnCode()
                + "<br>物料描述" + materials.getMatNameDesc()
                + "<br>盘点数量：" + checkDetail.getCdlNum() + "  盘点重量：" + checkDetail.getCdlWeight());

        return "";
    }

    /**
     * 损溢明细调整
     *
     * @param adjustmentApplyModel 查询条件
     * @return
     */
    public List<MAdjustmentApplyModel> findAdjustStockListByQuery(MAdjustmentApplyModel adjustmentApplyModel) {

        List<MAdjustmentApplyModel> adjustmentApplyModels = new ArrayList<MAdjustmentApplyModel>();

        // 判断是盘盈还是盘亏
        if (adjustmentApplyModel.getAjaCdlId() == null) {
            // 盘亏
            adjustmentApplyModels = adjustmentApplyDao.findAdjustStockLossListByQuery(adjustmentApplyModel);
        } else {
            MCheckDetail checkDetail = checkDetailDao.selectByPrimaryKey(adjustmentApplyModel.getAjaCdlId());
            if (checkDetail.getCdlCheckStatus().compareTo(1) == 0) {
                // 盘盈
                adjustmentApplyModels = adjustmentApplyDao.findAdjustStockProfitListByQuery(adjustmentApplyModel);
            } else if (checkDetail.getCdlCheckStatus().compareTo(2) == 0) {
                // 盘亏
                adjustmentApplyModels = adjustmentApplyDao.findAdjustStockLossListByQuery(adjustmentApplyModel);
            }
        }

        return adjustmentApplyModels;
    }

    /**
     * 保存损益调整记录（盘亏）
     *
     * @param adjustmentApply 调整记录
     * @return
     */
    @Transactional
    public String adjustLoss(MAdjustmentApply adjustmentApply) {

        String msg;

        adjustmentApply.setAjaItyStatus(1);// 调整状态：1保存状态 2提交审核申请 3二次提交 4审核通过
        MInventory inventory = inventoryDao.selectByPrimaryKey(adjustmentApply.getAjaItyId());
        MAdjustmentApply oldAdjustmentApply = new MAdjustmentApply();
        if (adjustmentApply.getAjaId() != null) {
            oldAdjustmentApply = adjustmentApplyDao.selectByPrimaryKey(adjustmentApply.getAjaId());
        }

        // a：可用数量 b：可用重量 c：本次调整数量 d：本次调整重量
        Double a = BigDecimalUtils.add(inventory.getItyAvaNum(), oldAdjustmentApply.getAjaNum() != null ? oldAdjustmentApply.getAjaNum() : 0.0);
        Double b = BigDecimalUtils.add(inventory.getItyAvaWeight(), oldAdjustmentApply.getAjaWeight() != null ? oldAdjustmentApply.getAjaWeight() : 0.0);
        Double c = adjustmentApply.getAjaNum() != null ? adjustmentApply.getAjaNum() : 0.0;
        Double d = adjustmentApply.getAjaWeight() != null ? adjustmentApply.getAjaWeight() : 0.0;

        // 判断该条在库明细可用量和在库量是否相等
        if (a.compareTo(inventory.getItyNum()) != 0 || b.compareTo(inventory.getItyWeight()) != 0) {
            return "该明细已经被标记，请先删除或审核标记记录！";
        }

        // 判断可用库存是否充足
        if (a.compareTo(c) < 0 || b.compareTo(d) < 0) {
            return "调整量大于在库量，调整失败！";
        }

        // 判断 盘点调整更新或新增
        if (adjustmentApply.getAjaId() != null) {
            adjustmentApplyDao.updateByPrimaryKey(adjustmentApply);
        } else {
            adjustmentApplyDao.insert(adjustmentApply);
        }

        // 减少库存在库明细可用数量
        inventory.setItyAvaNum(BigDecimalUtils.sub(a, c));
        inventory.setItyAvaWeight(BigDecimalUtils.sub(b, d));
        inventoryDao.updateByPrimaryKey(inventory);

        // 取得该损溢明细已调整总数量 原因：方便前台用户操作
        MAdjustmentApplyExample ex = new MAdjustmentApplyExample();
        MAdjustmentApplyExample.Criteria criteria = ex.createCriteria();
        criteria.andAjaCdlIdEqualTo(adjustmentApply.getAjaCdlId());
        List<MAdjustmentApply> adjustmentApplies = adjustmentApplyDao.selectByExample(ex);

        double adjustQtySum = 0;
        double adjustWeightSum = 0;
        for (int i = 0; i < adjustmentApplies.size(); i++) {
            adjustQtySum = adjustQtySum + (adjustmentApplies.get(i).getAjaNum() == null ? 0 : adjustmentApplies.get(i).getAjaNum());
            adjustWeightSum = adjustWeightSum + (adjustmentApplies.get(i).getAjaWeight() == null ? 0 : adjustmentApplies.get(i).getAjaWeight());
        }

        msg = String.valueOf(adjustQtySum) + "," + String.valueOf(adjustWeightSum);

        // 操作日志
        MMaterials materials = materialsDao.selectByPrimaryKey(inventory.getItyMatId());
        MCheckPlan checkPlan = checkPlanDao.selectByPrimaryKey(adjustmentApply.getAjaCpnId());
        logService.saveLog("损益明细调整（盘亏）", "盘点计划编号：" + checkPlan.getCpnCode()
                + "<br> 盘点物料：" + materials.getMatNameDesc() + "<br> 项目名称： " + inventory.getItyProName()
                + "<br> 调整数量： " + adjustmentApply.getAjaNum() + "    调整重量：" + adjustmentApply.getAjaWeight());

        return msg;
    }

    /**
     * 保存损益调整记录（盘盈）
     *
     * @param adjustmentApply 保存信息
     * @return json 数据
     */
    @Transactional
    public int adjustProfit(MAdjustmentApply adjustmentApply) {

        int rows;

        adjustmentApply.setAjaItyStatus(1);// 调整状态：1保存状态 2提交审核申请 3二次提交 4审核通过

        // 判断 盘点调整更新或新增
        if (adjustmentApply.getAjaId() != null) {
            rows = adjustmentApplyDao.updateByPrimaryKey(adjustmentApply);
        } else {
            rows = adjustmentApplyDao.insert(adjustmentApply);
        }

        // 操作日志
        MCheckDetail checkDetail = checkDetailDao.selectByPrimaryKey(adjustmentApply.getAjaCdlId());
        MMaterials materials = materialsDao.selectByPrimaryKey(checkDetail.getCdlMatId());
        MCheckPlan checkPlan = checkPlanDao.selectByPrimaryKey(adjustmentApply.getAjaCpnId());
        logService.saveLog("损益明细调整（盘盈）", "盘点计划编号：" + checkPlan.getCpnCode()
                + "<br> 盘点物料：" + materials.getMatNameDesc() + "<br> 项目名称：库存备件 "
                + "<br> 调整数量： " + adjustmentApply.getAjaNum() + "    调整重量：" + adjustmentApply.getAjaWeight());

        return rows;
    }

    /**
     * 更新盘点损益调整状态
     *
     * @param cpnId 盘点计划Id
     * @return
     */
    @Transactional
    public String updateAdjStatus(Integer cpnId) {

        // 判断 损益表状态为 3=已完成 时 不允许撤销（1是未开始，2是执行中，3是已完成）
        MCheckPlan checkPlan = checkPlanDao.selectByPrimaryKey(cpnId);
        if (checkPlan.getCpnPalStatus() == 3) {
            return "损溢表已提交，撤销失败。";
        }

        // 更新盘点损益调整
        if (checkPlan.getCpnAdjStatus() == 3) {
            checkPlan.setCpnAdjStatus(2);
            checkPlan.setCpnPalStatus(1);
        } else {
            checkPlan.setCpnAdjStatus(3);
            checkPlan.setCpnPalStatus(2);
        }
        checkPlanDao.updateByPrimaryKey(checkPlan);

        // 批量更新损溢明细调整状态
        MAdjustmentApply adjustmentApply = new MAdjustmentApply();
        if (checkPlan.getCpnAdjStatus() == 3) {
            adjustmentApply.setAjaItyStatus(2);    // 1保存状态 2提交审核申请 3二次提交 4审核通过
        } else {
            adjustmentApply.setAjaItyStatus(1);    // 1保存状态 2提交审核申请 3二次提交 4审核通过
        }

        MAdjustmentApplyExample ex = new MAdjustmentApplyExample();
        MAdjustmentApplyExample.Criteria criteria = ex.createCriteria();
        criteria.andAjaCpnIdEqualTo(cpnId);
        adjustmentApplyDao.updateByExampleSelective(adjustmentApply, ex);

        logService.saveLog(checkPlan.getCpnAdjStatus() == 3 ? "提交盘点损益调整结果" : "撤销盘点损益调整结果", "盘点计划编号：" + checkPlan.getCpnCode());
        return checkPlan.getCpnAdjStatus() == 3 ? "提交成功" : "撤销成功";
    }

    /**
     * 损溢明细调整
     *
     * @param adjustmentApplyModel 查询条件
     * @return
     */
    public List<MAdjustmentApplyModel> findResultCommitListByQuery(MAdjustmentApplyModel adjustmentApplyModel) {

        return adjustmentApplyDao.findResultCommitListByQuery(adjustmentApplyModel);
    }

    /**
     * 选中行损益汇总
     *
     * @param checkResultCommitSumModel 查询条件
     * @return
     */
    public List<MCheckResultCommitSumModel> findResultCommitSumByQuery(MCheckResultCommitSumModel checkResultCommitSumModel) {

        return adjustmentApplyDao.findResultCommitSumByQuery(checkResultCommitSumModel);
    }

    /**
     * 更新盘点状态
     *
     * @param cpnId 盘点计划Id
     * @return
     */
    @Transactional
    public String updatePalStatus(Integer cpnId) {

        // 判断 如果库存调整已经审批 则不允许撤销
        MAdjustmentApplyExample ex1 = new MAdjustmentApplyExample();
        MAdjustmentApplyExample.Criteria criteria1 = ex1.createCriteria();
        criteria1.andAjaCpnIdEqualTo(cpnId);
        criteria1.andAjaItyStatusEqualTo(4);
        List<MAdjustmentApply> adjustmentApplies = adjustmentApplyDao.selectByExample(ex1);
        if (adjustmentApplies.size() > 0) {
            return "盘点损益已经被审核，本次操作失败";
        }

        Boolean commitFlg = true;   // 提交标识
        // 盘点计划字段
        Integer cpnStatus = 3;
        Integer cpnPalStatus = 3;

        // 损溢调整字段
        Integer ajaItyStatus = 3;
        Date ajaDate = new Date();
        String ajaProposer = ShiroUtils.getUser().getName();

        MCheckPlan checkPlan = checkPlanDao.selectByPrimaryKey(cpnId);
        if (checkPlan.getCpnPalStatus() == 3) {
            // 本次执行的是撤销操作
            cpnStatus = 2;
            cpnPalStatus = 2;
            ajaItyStatus = 2;
            ajaDate = null;
            ajaProposer = null;
            commitFlg = false;
        }

        // 更新盘点计划状态
        checkPlan.setCpnStatus(cpnStatus);  // 状态 0删除 1未开始 2执行中 3已完成
        checkPlan.setCpnPalStatus(cpnPalStatus);   // 损益表状态 1是未开始，2是执行中，3是已完成
        checkPlanDao.updateByPrimaryKey(checkPlan);

        // 更新损溢调整状态
        MAdjustmentApply adjustmentApply = new MAdjustmentApply();
        adjustmentApply.setAjaItyStatus(ajaItyStatus);    // 1保存状态 2提交审核申请 3二次提交 4审核通过
        adjustmentApply.setAjaDate(ajaDate);
        adjustmentApply.setAjaProposer(ajaProposer);

        MAdjustmentApplyExample ex = new MAdjustmentApplyExample();
        MAdjustmentApplyExample.Criteria criteria = ex.createCriteria();
        criteria.andAjaCpnIdEqualTo(cpnId);
        adjustmentApplyDao.updateByExampleSelective(adjustmentApply, ex);

        // 操作库存调整审批表
        MAdjustmentApplyModel adjustmentApplyModel = new MAdjustmentApplyModel();
        adjustmentApplyModel.setCpnId(cpnId);
        List<MAdjustmentApplyModel> adjustmentApplyModels = adjustmentApplyDao.findResultCommitListByQuery(adjustmentApplyModel);

        MAdjust adjust;
        MAdjustmentApply mAdjustmentApply;
        if (commitFlg) {
            // 提交：循环插入调整申请表
            if (adjustmentApplyModels != null && adjustmentApplyModels.size() > 0) {
                for (int i = 0; i < adjustmentApplyModels.size(); i++) {
                    adjust = new MAdjust();
                    adjust.setAdjInType(adjustmentApplyModels.get(i).getItyInType());
                    adjust.setAdjMatDesc(adjustmentApplyModels.get(i).getMatNameDesc());
                    adjust.setAdjDate(new Date());
                    adjust.setAdjPerson(ShiroUtils.getUser().getName());
                    adjust.setAdjProjectCode(adjustmentApplyModels.get(i).getAdjProjectCode());
                    adjust.setAdjProjectName(adjustmentApplyModels.get(i).getAdjProjectName());
                    adjust.setAdjReason("库存盘点");
                    adjust.setAdjSpec(adjustmentApplyModels.get(i).getItySpec());
                    adjust.setAdjStatus(3);
                    adjust.setAdjTrackCode(adjustmentApplyModels.get(i).getItyTrackCode());
                    adjust.setAdjAfterMatId(adjustmentApplyModels.get(i).getAjaMatId());
                    adjust.setAdjAfterItyId(adjustmentApplyModels.get(i).getAjaItyId());
                    adjust.setAdjPrice(adjustmentApplyModels.get(i).getCdlPrice());
                    adjust.setAdjBeforePrice(adjustmentApplyModels.get(i).getCdlPrice());
                    adjust.setAdjType(2);
                    adjust.setAdjNum(adjustmentApplyModels.get(i).getAjaNum());
                    adjust.setAdjWeight(adjustmentApplyModels.get(i).getAjaWeight());
                    adjust.setAdjPalValStatus(adjustmentApplyModels.get(i).getProfitLossFlg());
                    adjust.setAdjAjaId(adjustmentApplyModels.get(i).getAjaId());
                    adjustDao.insert(adjust);

                    // 回写库存调整外键
                    mAdjustmentApply = new MAdjustmentApply();
                    mAdjustmentApply.setAjaId(adjustmentApplyModels.get(i).getAjaId());
                    mAdjustmentApply.setAjaAdjId(adjust.getAdjId());
                    adjustmentApplyDao.updateByPrimaryKeySelective(mAdjustmentApply);
                }
            }
        } else {
            // 撤销：批量删除已经提交数据
            for (int i = 0; i < adjustmentApplyModels.size(); i++) {

                // 回写库存调整外键
                mAdjustmentApply = adjustmentApplyDao.selectByPrimaryKey(adjustmentApplyModels.get(i).getAjaId());
                mAdjustmentApply.setAjaAdjId(null);
                adjustmentApplyDao.updateByPrimaryKey(mAdjustmentApply);

                adjust = new MAdjust();
                adjust.setAdjId(adjustmentApplyModels.get(i).getAjaAdjId());
                adjustDao.deleteByPrimaryKey(adjust.getAdjId());
            }
        }

        logService.saveLog(checkPlan.getCpnPalStatus() == 3 ? "提交盘点损益表" : "撤销盘点损益表", "盘点计划编号：" + checkPlan.getCpnCode());
        return checkPlan.getCpnPalStatus() == 3 ? "提交成功" : "撤销成功";
    }

}
